
package com.chuanke.ckfamily.service.social.impl;

import com.alibaba.fastjson.JSONObject;
import com.chuanke.ckfamily.dao.base.CkUtil;
import com.chuanke.ckfamily.dao.base.Page;
import com.chuanke.ckfamily.dao.finance.model.FamilyDayIncome;
import com.chuanke.ckfamily.dao.social.FamilyDao;
import com.chuanke.ckfamily.dao.social.model.Family;
import com.chuanke.ckfamily.dao.social.model.FamilyMember;
import com.chuanke.ckfamily.dao.user.model.User;
import com.chuanke.ckfamily.service.base.FailCode;
import com.chuanke.ckfamily.service.base.FamilyValidator;
import com.chuanke.ckfamily.service.common.CacheService;
import com.chuanke.ckfamily.service.common.CacheService.KEY_PREFIX;
import com.chuanke.ckfamily.service.common.SysConfigService;
import com.chuanke.ckfamily.service.common.TipsService;
import com.chuanke.ckfamily.service.common.WyService;
import com.chuanke.ckfamily.service.common.impl.RedisLockUtil;
import com.chuanke.ckfamily.service.constant.*;
import com.chuanke.ckfamily.service.exception.CFException;
import com.chuanke.ckfamily.service.exception.FamilyExcepiton;
import com.chuanke.ckfamily.service.finance.FamilyDayIncomeService;
import com.chuanke.ckfamily.service.finance.PacketFinaceService;
import com.chuanke.ckfamily.service.finance.UserDayIncomeService;
import com.chuanke.ckfamily.service.social.FamilyMemberService;
import com.chuanke.ckfamily.service.social.FamilyService;
import com.chuanke.ckfamily.service.social.thread.LoadFansToFamilyThread;
import com.chuanke.ckfamily.service.user.UserService;
import com.chuanke.ckfamily.service.util.CkServerUtil;
import com.chuanke.ckfamily.service.util.OssUtil;
import com.clusterswisdom.kid.server.libary.model.DataRecord;
import com.weijie.core.BaseBiz;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.ParseException;
import org.h2.store.DataReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional(rollbackFor=Exception.class)
public class FamilyServiceImpl extends BaseBiz<Family, FamilyDao> implements FamilyService {

	private static final Logger log = LoggerFactory.getLogger(FamilyServiceImpl.class);

	public static final Long DAY_SPAN = 3600 * 24 * 1000l;

	@Autowired
	private UserService userService;

	@Autowired
	private FamilyMemberService familyMemberService;

	@Autowired
	private FamilyService familyService;

	@Autowired
	private FamilyDayIncomeService familyDayIncomeService;

	@Autowired
	private SysConfigService sysConfigService;

	@Autowired
	private TipsService tipsService;
	
	@Autowired
	private PacketFinaceService packetFinaceService;

	@Autowired
	private WyService wyService;

	@Autowired
	private CacheService cacheService;

	@Autowired
	private UserDayIncomeService userDayIncomeService;

	@Override 
	public void update(Family family) {
		super.update(family);
	}

	@Override
	public Integer addFmebmer(Long fid, Long cation) {
		RedisLockUtil lock = null;
		try {
			lock = cacheService.getLock(CacheService.KEY_PREFIX.familyMnum_.name() + fid);
			Integer fnum = getFmember(fid);
			if (fnum >= cation) {
				return -1;
			}

			fnum += 1;

			Family familyParam = new Family();
			familyParam.setId(fid);
			familyParam.setMnum(fnum);
			familyService.update(familyParam);

			cacheService.set(CacheService.KEY_PREFIX.familyMnum_.name() + fid, fnum);
			return fnum;

		} catch (Exception e) {
			e.printStackTrace();
			return -1;

		} finally {
			if (lock != null) {
				lock.unlock();
			}

		}
	}

	@Override
	public Integer reduceFmember(Long fid) {
		RedisLockUtil lock = null;
		try {
			lock = cacheService.getLock(CacheService.KEY_PREFIX.familyMnum_.name() + fid);
			Integer fnum = getFmember(fid);
			if (fnum < 1) {
				return -1;
			}

			fnum -= 1;

			Family familyParam = new Family();
			familyParam.setId(fid);
			familyParam.setMnum(fnum);
			familyService.update(familyParam);

			cacheService.set(CacheService.KEY_PREFIX.familyMnum_.name() + fid, fnum);
			return fnum;

		} catch (Exception e) {
			e.printStackTrace();
			return -1;

		} finally {
			if (lock != null) {
				lock.unlock();
			}

		}
	}

	@Override
	public Integer getFmember(Long fid) {
		Integer fnum = (Integer)cacheService.get(CacheService.KEY_PREFIX.familyMnum_.name() + fid);
		if (fnum == null) {
			Family family = findByIdForUpdate(fid);
			if (family == null) {
				return 0;
			}

			fnum = family.getMnum();
			cacheService.set(CacheService.KEY_PREFIX.familyMnum_.name() + fid, family.getMnum());
		}

		return fnum;
	}

	@Override
	public  Family findByIdForUpdate(Long id) {
		
		return baseDao.findByIdForUpdate(id);
	}

	@Override
	public Map<String, Object> fansFamily(Long uid, String keyword,Integer p){
		Map<String, Object>  result=new HashMap<>();

		Map<String, Object> param=new HashMap<>();
		param.put("user_id", uid);
		param.put("keyword", keyword);
		Page page = p != null ? new Page(p) : null;

		List<Family> list = baseDao.findFansFamily(param,page);

		Integer count = baseDao.findFansFamilyCount(param);
		result.put("result", list);
		result.put("total", count);
		return result;

	}

	@Override
	public Family familyUpdate(Long uid, String tid, String announcement, String icon, String familyName) throws CFException, ParseException, IOException {
		Family family = getByOwner(uid);
		if (family == null) {
			throw new CFException(FailCode.PERMISSIONS_FAMILY_OWNER);
		}

		User user = userService.findById(uid);
		if(user==null){
			throw new CFException(FailCode.USER_NOT_EXIST);
		}

		if(StringUtils.isBlank(announcement) && StringUtils.isBlank(icon)  && StringUtils.isBlank(familyName)){
			if(announcement!=null && announcement.trim().isEmpty()){
				throw new CFException(FailCode.PARAMS_ERROR,"家族公告不能为空");
			}else if(familyName!=null && familyName.trim().isEmpty()){
				throw new CFException(FailCode.PARAMS_ERROR,"家族名称不能为空");
			}else{
				throw new CFException(FailCode.PARAMS_ERROR,"非法参数");
			}

		}
		Family familyParam=new Family();
		familyParam.setId(family.getId());

		String ficon=null;
		if (StringUtils.isNotBlank(icon)) {
			ficon=OssUtil.getFamilyIcon(icon);
			familyParam.setFicon(ficon);
		}
		String announcement_timeStr="";
		if (StringUtils.isNotBlank(announcement)) {
			if(announcement.length()>FamilyValidator.familyAnnouncement_length){
				throw new FamilyExcepiton(FailCode.PARAMS_ERROR, "家族公告    必须不能超过"+FamilyValidator.familyAnnouncement_length+"个字符");
			}
			familyParam.setAnnouncement(announcement);
			familyParam.setAnnouncement_time(new Timestamp(System.currentTimeMillis()));
			announcement_timeStr=familyParam.getAnnouncement_timeStr();
			//清空公告读取状态
			baseDao.updateAnnouncementRead(family.getId());
		}

		if (StringUtils.isNotBlank(familyName)) {
			if(familyName.length()>FamilyValidator.familyName_length){
				throw new FamilyExcepiton(FailCode.PARAMS_ERROR, "家族名称必须不能超过"+FamilyValidator.familyName_length+"个字符");
			}

			familyParam.setName(familyName);
		}

		if (StringUtils.isNotBlank(announcement)) {
			//修改群公告，推送消息
			JSONObject ext=new JSONObject();
			ext.put("msgtype", MsgEunm.family_update_announcement.getMsgtype());
			ext.put("owner_user_name", user.getNick_name());
			ext.put("owner_user_no", user.getUser_no());
			ext.put("announcement_timeStr", announcement_timeStr);
			ext.put("ficon", family.getFicon());
			ext.put("announcement", announcement);
			ext.put("name", family.getName());
			ext.put("tid", family.getTid());
			ext.put("is_read", false);
			wyService.sendMsgForTeam(family.getOwner_user_no(), family.getTid(), user.getNick_name()+"更新了家族公告", ext);

		}else{
			wyService.updateTeam(family,ficon,familyName,announcement);

		}
		this.update(familyParam);
		return family;
	}

	@Override
	public Map<String, Object> familyMember(Long uid, String nickName,int sort, Integer order, Long date, Integer p,String tid)throws ParseException, java.text.ParseException, CFException{
		FamilyMember familyMember = familyMemberService.findByUserId(uid);
		if (familyMember == null) {
			throw new CFException(FailCode.FAMILY_MEMBER_NOT_EXIST);
		}
		Family family = findById(familyMember.getFamily_id());
		FamilyValidator.validateFamilyTid(family, tid);

		Long familyId=familyMember.getFamily_id();

		Map<String, Object>  result=new HashMap<>();
		Long owner_user_id = family.getOwner_user_id();
		User user = userService.findById(owner_user_id);
		result.put("owner", user);

		Map<String, Object>  param=new HashMap<>();
		param.put("family_id", familyId);
		param.put("nick_name", nickName);

		if(order!=null){
			param.put("column_order", order==1?"asc":"desc");
		}
		result.put("memberCount", familyMemberService.searchCountByFamilyId(familyMember.getFamily_id()));//当前成员数
		List<Map<String, Object>> members=null;
		switch (sort) {
		case 1:
			Map<String, Object> defaultMembers=searchDefaultFamilyMember(familyId,date,p,owner_user_id);
			result.put("members", defaultMembers);
			return result;
		case 2:
			param.put("column_sort", "u.active_time");
			members= searchFamilyMember(param,family,p);
			result.put("members", members);
			return result;
		case 3:
			param.put("column_sort", "fm.devote_sum");
			members= searchFamilyMember(param,family,p);
			result.put("members", members);
			return result;
		case 4:
			param.put("column_sort", "fm.create_time");
			members= searchFamilyMember(param,family,p);
			result.put("members", members);
			return result;
		default:
			throw new FamilyExcepiton(FailCode.PARAMS_ERROR);
		}


	}

	private Map<String, Object> searchDefaultFamilyMember(Long family_id,Long date,Integer p,Long owner_user_id) throws ParseException, java.text.ParseException {
		Map<String, Object> result=new HashMap<>();
		Map<String, Object> param=new HashMap<>();
		//返回所有
		if(date==null){
			Page page = p != null ? new Page(p, Page.PAGE_SIZE_50) : null;
			param.put("family_id", family_id);
			List<Map<String, Object>>  newMember=baseDao.searchFamilyMember(param,page);
			newMember=searchFamilyMemberFormat(newMember);
			result.put("newMember", newMember);
		}else{
			Timestamp timestamp = new Timestamp((date-600000)); //防止在拉取过程中新增或者更新
			
			param.clear();
			param.put("is_delete", 0);
			param.put("family_id", family_id);
			param.put("gt_update_time", timestamp);
			param.put("flag", "updateMember");
			List<Map<String, Object>>  updateMember=baseDao.searchFamilyMember(param,null);
			updateMember=searchFamilyMemberFormat(updateMember);

			param.clear();
			param.put("family_id", family_id);
			param.put("gt_update_time", timestamp);
			param.put("is_delete", 1);
			param.put("flag", "removedMember");
			List<Map<String, Object>>  removedMember=baseDao.searchFamilyMember(param,null);
			removedMember=searchFamilyMemberFormat(removedMember);
			
			if (updateMember != null && !updateMember.isEmpty() && removedMember != null && !removedMember.isEmpty()) {
				for (Map<String, Object> updateMap : updateMember) {
					String userNo = MapUtils.getString(updateMap, "user_no");

					Iterator<Map<String, Object>> iterator = removedMember.iterator();
					while (iterator.hasNext()) {
						Map<String, Object> removedMap = iterator.next();
						String userNo2 = MapUtils.getString(removedMap,"user_no");
						if (userNo.equals(userNo2)) {
							iterator.remove();
						}
					}
				}

			}
			result.put("updateMember", updateMember);
			result.put("removedMember", removedMember);
			
		}
		
		result.put("date", new Date().getTime());
		return result;
	}

	private List<Map<String, Object>> searchFamilyMemberFormat(List<Map<String, Object>> members) throws ParseException,java.text.ParseException {
		if (members != null && !members.isEmpty()) {
			Date today = new Date();
			for (Map<String, Object> map : members) {
				long devote_sum = MapUtils.getLongValue(map, "devote_sum", 0l);
				map.put("devote_sumStr", CkUtil.formatMoney(devote_sum));
				boolean is_active = false;
				if (map.get("active_time") != null) {
					Timestamp active_time = (Timestamp) map.get("active_time");
					Date smdate = new Date(active_time.getTime());
					int days = daysBetween(smdate, today);
					if (days == 0) {
						is_active = true;
						map.put("activeStr", "活跃");

					}else{
						map.put("activeStr", "[未活跃" + (days) + "天]");

					}

				} else {
					map.put("activeStr", "[未活跃]");

				}

				map.put("is_active", is_active);
			}
		}
		return members;
	}



	private List<Map<String, Object>> searchFamilyMember(Map<String, Object> param,Family family,Integer p) throws ParseException, java.text.ParseException {

		List<Map<String, Object>>  list=baseDao.searchFamilyMember(param,new Page(p));
		List<Map<String, Object>> newlist=searchFamilyMemberFormat(list);
		return newlist;
	}

	@Override
	public List<Family> findFamilyBySuperId(Long superId) {
		return this.baseDao.findFamilyBySuperId(superId);
	}

	/**
	 * @param smdate 较小的时间
     * @param bdate  较大的时间
	 * @throws java.text.ParseException
	 */
	public static int daysBetween(Date smdate, Date bdate) throws ParseException, java.text.ParseException {
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//		smdate = sdf.parse(sdf.format(smdate));
//		bdate = sdf.parse(sdf.format(bdate));
//		Calendar cal = Calendar.getInstance();
//		cal.setTime(smdate);
//		long time1 = cal.getTimeInMillis();
//		cal.setTime(bdate);
//		long time2 = cal.getTimeInMillis();

		return (int)((bdate.getTime() - smdate.getTime()) / DAY_SPAN);
	}

	public static void main(String[] args) throws java.text.ParseException {
		System.out.println(CkUtil.formatMoney(19l));
	}


	@Override
	public Map<String, Object> income(Long userId,String tid)throws CFException{
		User user = userService.findById(userId);
		if(user==null){
			throw new FamilyExcepiton(FailCode.USER_NOT_EXIST);
		}
		FamilyMember familyMember = familyMemberService.findByUserId(userId);
		if(familyMember==null){
			throw new FamilyExcepiton(FailCode.FAMILY_MEMBER_NOT_EXIST);
		}
		Family family = findById(familyMember.getFamily_id());
		FamilyValidator.validateFamilyTid(family, tid);

		String tday = CkUtil.getNowDayStr();//今天
		String yday = CkUtil.getYesterdayStr();//昨天

		Map<String,Object> result=new HashMap<>();

		Map<String,Object> familyMap=new HashMap<>();
		FamilyDayIncome tdayIncomeFamily = familyDayIncomeService.findByDate(family.getId(),tday);
		FamilyDayIncome ydayIncomeFamily = familyDayIncomeService.findByDate(family.getId(),yday);

		String family_tips=null;
		try {
			family_tips = tipsService.getFamilyIncomeTips();
		}  catch (Exception e) {
		}
		String packet_tips=null;
		try {
			packet_tips = tipsService.getFamilyRedpacketTips();
		}  catch (Exception e) {
		}
		String owner_tips=null;
		try {
			owner_tips = tipsService.getLeaderIncomeTips();
		}  catch (Exception e) {
		}
		String owner_super=null;
		try {
			owner_super = tipsService.getLeaderSuperIncomeTips();
		}  catch (Exception e) {
		}

		familyMap.put("tday_income", tdayIncomeFamily !=null ? CkUtil.formatMoney(tdayIncomeFamily.getAll_money()) : CkUtil.ZERO_MONEY);
		familyMap.put("yday_income", ydayIncomeFamily !=null ? CkUtil.formatMoney(ydayIncomeFamily.getAll_money()): CkUtil.ZERO_MONEY);
		familyMap.put("income_sum", CkUtil.formatMoney(family.getFamily_income_sum()));
		familyMap.put("tips",family_tips!=null?family_tips:"");


		Map<String,Object> packetMap=new HashMap<>();
		packetMap.put("income_sum", CkUtil.formatMoney(family.getPacket_income_sum()));
		packetMap.put("balabce", CkUtil.formatMoney(family.getBalance()));
		packetMap.put("tips",packet_tips!=null?packet_tips:"");


		Map<String,Object> ownerMap=new HashMap<>();
		ownerMap.put("income_sum", CkUtil.formatMoney(family.getOwner_income_sum()));
		ownerMap.put("yday_income", ydayIncomeFamily !=null ? CkUtil.formatMoney(ydayIncomeFamily.getLead_pay()): CkUtil.ZERO_MONEY);
		ownerMap.put("tips",owner_tips!=null?owner_tips:"");

		Map<String,Object> superMap=new HashMap<>();
		superMap.put("income_sum", CkUtil.formatMoney(family.getSuper_income_sum()));
		superMap.put("yday_income", ydayIncomeFamily !=null? CkUtil.formatMoney(ydayIncomeFamily.getS_lead_pay()): CkUtil.ZERO_MONEY);
		superMap.put("tips",owner_super!=null?owner_super:"");


		result.put("family", familyMap); //家族收益
		result.put("packet", packetMap);//家族红包
		result.put("owner", ownerMap);//族长分成
		result.put("owner_super", superMap);//族长上线分成
		return result;

	}

	public void fixFamilyMember() {
		List<Family> families = findAll();
		if (families == null) {
			return;
		}

		for (Family family: families) {
			Long rnum = baseDao.getFamilyMemberNum(family.getId());
			if (rnum.intValue() != family.getMnum().intValue()) {
				Family update = new Family();
				update.setId(family.getId());
				update.setMnum(rnum.intValue());
				log.info("fixFamilyMember =======> udpate faimly={}, mnum={}, rnum={}", family.getName(), family.getMnum(), rnum);
				baseDao.update(update);
				cacheService.delete(KEY_PREFIX.familyMnum_.name() + family.getId());
			}

			if (rnum > 500) {
				int tickNum = rnum.intValue() - 500;
				List<User> members = familyMemberService.getMembers(family.getId());
				for (User user: members) {
					if (!user.hasWyId()) {
						try {
							if (familyMemberService.leaveFamily(user.getId(), true, family.getTid())) {
								tickNum--;
								log.info("fixFamilyMember =======> leave faimly={}, mnum={}, rnum={}, tickNum={}, user={}, wy_token={}, super_id={}", family.getName(), family.getMnum(), rnum, tickNum, user.getId(), user.getWy_token(), user.getSuper_id());
							}
						} catch (Exception e) {
							e.printStackTrace();
						} 

						if (tickNum < 1) {
							break;
						}
					}
				}
			}
		}
	}

	public void fixFamily(Long fid, Long uid) throws CFException {
		Family family = findById(fid);
		User user = userService.findById(uid);

		try {
			//2 将族长加入家族
			familyMemberService.addFamilyMember(family, user, false, true);

			long money = sysConfigService.getLongValue(SysConfigKeyEnum.user_family_money.name(), FamilyConstance.USER_FAMILY_MONEY);
			packetFinaceService.addForSystem(family.getId(), money);

		} catch (Exception e) {
			e.printStackTrace();

		}

		try {
			if (CkServerUtil.online) {
				String customWelcomeMsg = sysConfigService.getValue(SysConfigKeyEnum.customWelcomeMsg.name());
				String customUserNo = sysConfigService.getValue(SysConfigKeyEnum.customUserNo.name());
				String msg = String.format("我创建了家族%s", user.getNick_name(), family.getName());
				wyService.sendMsgForUser(user.getUser_no(), customUserNo, 0, msg, null);
				wyService.sendMsgForUser(customUserNo, user.getUser_no(), 0, customWelcomeMsg, null);
			}
		} catch (Exception e) {
			e.printStackTrace();

		}

		//3.粉丝自动拉入本家族（排除已当族长的下线粉丝，粉丝大于500人的，以最后登陆时间倒叙，取前500人
		if (family.getType() == FamilyType.USER_FAMILY.getType()) {
			LoadFansToFamilyThread.load(uid, family, true, this, familyMemberService, sysConfigService);
		}
	}


	@Override
	public Family createFamily(Long userId, String familyName, String icon) throws Exception {
		if (StringUtils.isBlank(familyName)) {
			throw new FamilyExcepiton(FailCode.PARAMS_ERROR, "家族名称不可以为空");
		}

		if (familyName.length() > FamilyValidator.familyName_length) {
			throw new FamilyExcepiton(FailCode.PARAMS_ERROR, "家族名称必须不能超过" + FamilyValidator.familyName_length + "个字符");
		}

		User user = userService.findById(userId);
		if (user == null) {
			throw new FamilyExcepiton(FailCode.USER_NOT_EXIST);
		}

		if (user.getIs_header() != null && user.getIs_header() == 1) {
			log.debug("is header======> uid={}, isHeader={}", user.getId(), user.getIs_header());
			throw new FamilyExcepiton(FailCode.APP, "已经是族长");
		}
		Family f = this.findFamilyByUserId(userId);
		if (f != null && f.getOwner_user_id().equals(userId)) {
			log.debug("is header======> uid={}, isHeader={}", user.getId(), user.getIs_header());
			throw new FamilyExcepiton(FailCode.APP, "已经是族长");
		}

		Map<String, Object> param = new HashMap<>();
		param.put("super_id", userId);
		Integer searchCount = userService.searchCount(param);
		int create_family_fans_num = sysConfigService.getIntegerValue(SysConfigKeyEnum.create_family_fans_num.toString(), FamilyConstance.FAMILY_INITIALSIZE);

		if (searchCount < create_family_fans_num) {
			throw new FamilyExcepiton(FailCode.APP, "粉丝滿足" + create_family_fans_num + "的用户才可以自建家族哟");
		}
		//1.创建家族
		int capcity = sysConfigService.getIntegerValue(SysConfigKeyEnum.user_family_max.name(), FamilyConstance.FAMILY_CAPACITY);
		Family family = new Family();
		family.setAnnouncement("");
		family.setBalance(0l);
		family.setCreate_time(new Timestamp(System.currentTimeMillis()));
		family.setUpdate_time(new Timestamp(System.currentTimeMillis()));
		family.setFicon(OssUtil.getFamilyIcon(icon));
		family.setIntro("");
		family.setName(familyName);
		family.setType(FamilyType.USER_FAMILY.getType());
		family.setOwner_user_id(userId);
		family.setOwner_user_no(user.getUser_no());
		family.setSuper_id(user.getSuper_id());
		family.setFcapacity(capcity);
		family.setMnum(0);

		String tid = null;
		try {
			tid = wyService.createTeam(family);
			family.setTid(tid);
			this.save(family);

			//3 创建家族后  将user表的is_header 更新1 表明是族长用户
			User userParam = new User();
			userParam.setId(user.getId());
			userParam.setIs_header(1);
			userService.update(userParam);

		} catch (Exception e) {
			e.printStackTrace();

		}

		try {
			//2 将族长加入家族
			familyMemberService.addFamilyMember(family, user, false, true);

			long money = sysConfigService.getLongValue(SysConfigKeyEnum.user_family_money.name(), FamilyConstance.USER_FAMILY_MONEY);
			packetFinaceService.addForSystem(family.getId(), money);

		} catch (Exception e) {
			if (tid != null) {
				wyService.removeTeam(tid, family.getOwner_user_no());
			}
			throw e;

		}

		try {
			if (CkServerUtil.online) {
				String customWelcomeMsg = sysConfigService.getValue(SysConfigKeyEnum.customWelcomeMsg.name());
				String customUserNo = sysConfigService.getValue(SysConfigKeyEnum.customUserNo.name());
				String msg = String.format("我创建了家族%s", user.getNick_name(), familyName);
				wyService.sendMsgForUser(user.getUser_no(), customUserNo, 0, msg, null);
				wyService.sendMsgForUser(customUserNo, user.getUser_no(), 0, customWelcomeMsg, null);
			}
		} catch (Exception e) {
			e.printStackTrace();

		}

		//3.粉丝自动拉入本家族（排除已当族长的下线粉丝，粉丝大于500人的，以最后登陆时间倒叙，取前500人
		if (family.getType() == FamilyType.USER_FAMILY.getType()) {
			LoadFansToFamilyThread.load(userId, family, true, this, familyMemberService, sysConfigService);
		}

		return family;
	}

	@Override
	public Map<String, Object> familyInfo(Long userId, Long familyId,String tid) throws FamilyExcepiton, CFException {
		Map<String, Object> result=new HashMap<>();
	 	Family family = null;
		if (familyId == null) { //查询自己家族
			FamilyMember familyMember = familyMemberService.findByUserId(userId);
			if(familyMember==null){
				throw new FamilyExcepiton(FailCode.FAMILY_MEMBER_NOT_EXIST);
			}
			family = findById(familyMember.getFamily_id());
			FamilyValidator.validateFamilyTid(family, tid);


			if(family.getId()!=familyMember.getFamily_id().longValue()){
				throw new FamilyExcepiton(FailCode.FAMILY_MEMBER_NOT_EXIST);
			}

			User user = userService.findById(userId);

			if(user==null){
				throw new FamilyExcepiton(FailCode.USER_NOT_EXIST);
			}
			User owner_user = userService.findById(family.getOwner_user_id());

			//当前家族成员是否可以退出家族（退出家族前提条件：群主三天未登录）
			long loginSuperLoginTime = sysConfigService.getLongValue(SysConfigKeyEnum.leave_login_time.toString(),FamilyConstance.LEADER_LOST_TIME_SPAN);
			if (owner_user.getActive_time()!=null && System.currentTimeMillis() - owner_user.getActive_time().getTime() < loginSuperLoginTime) {
				result.put("is_leave", false);
			}else{
				result.put("is_leave", true);
			}
			//是否是族长 0不是  1是
			result.put("is_header", user.getIs_header());
			//是否消息免打扰。0：否 1：是
			result.put("nocall", familyMember.getNocall());
			//是否家族屏蔽消息 0：否 1：是
			result.put("shield", familyMember.getShield());

		} else { //查询指定家族
			family = findById(familyId);
			FamilyValidator.validateFamilyTid(family, tid);
		}

		if(family == null){
			throw new FamilyExcepiton(FailCode.FAMILY_NOT_EXIST);
		}
		User owner = userService.findById(family.getOwner_user_id());
		
		result.put("ownerName", owner.getNick_name());
		result.put("family", family);
		result.put("members", familyMemberService.getTopMembers(family.getId()));
		result.put("memberCount", familyMemberService.searchCountByFamilyId(family.getId()));//当前成员数
		result.put("memberMaxCount", family.getFcapacity()); //家族最大成员数

		Family userFamily = findFamilyByUserId(userId);
		boolean isMember = userFamily != null && userFamily.getId().longValue() == family.getId();
		result.put("is_member", isMember);
		return result;
	}



	@Override
	public Map<String, Object> myFamily(Long userId) throws Exception {
		User user = userService.findById(userId);
		if (user == null) {
			throw new FamilyExcepiton(FailCode.USER_NOT_EXIST);
		}

		Family myFamily = findFamilyByUserId(userId);
		boolean addFamily=true;
		if (myFamily == null) {
			addFamily = addFamilyBylogin(userId, null);
		}
		if(!addFamily){
			throw new FamilyExcepiton(FailCode.FAMILY_NOT_EXIST, "用户" + userId + ",家族不存在！");
		}

		Map<String, Object> result=new HashMap<>();
		result.put("myFamily", myFamily);
		// 用户的is_header为空时 返回0表示普通用户   1表示族长
		if(user.getIs_header() == null){
			result.put("is_header", 0);
		}else {
			result.put("is_header", user.getIs_header());
		}

		//家族排行榜
		List<Long> topFamily = this.getFamilyByRank();
		List<Map<String, Object>> list = formatTopFamily(userId,topFamily);
		result.put("topFamily", list);

		return result;
	}

	private List<Long> getFamilyByRank() {
		List<Long> list = (List<Long>) cacheService.get(KEY_PREFIX.familyRank_.name());
		if (list == null) {
			list = baseDao.getFamilyByRank(10);
			if (list != null && !list.isEmpty()) {
				cacheService.set(KEY_PREFIX.familyRank_.name(), list,86400000l);
			}
		}
		return list;
	}

	@Override
	public Map<String, Object>  familyNocall(Long uid, int nocall, String tid) throws CFException, ParseException, IOException{
		User user = userService.findById(uid);
		if (user == null) {
			throw new FamilyExcepiton(FailCode.USER_NOT_EXIST);
		}

		FamilyMember familyMember = familyMemberService.findByUserId(uid);
		if (familyMember == null) {
			throw new FamilyExcepiton(FailCode.FAMILY_MEMBER_NOT_EXIST);
		}
		Family family = findById(familyMember.getFamily_id());
		FamilyValidator.validateFamilyTid(family, tid);
		Map<String, Object> result=new HashMap<>();
		if(nocall == 0){
			if(familyMember.getNocall()==null || familyMember.getNocall() == nocall){
				throw new FamilyExcepiton(FailCode.APP, "你已经关闭消息免打扰");
			}
		   
			 updateNocall(family, familyMember, user.getUser_no(), nocall);

		}else if(nocall == 1){
			if(familyMember.getNocall() != null && familyMember.getNocall()==nocall){
				throw new FamilyExcepiton(FailCode.APP, "你已经开启消息免打扰");
			}
		  
		    updateNocall(family, familyMember,user.getUser_no(), nocall);

		}else{
			throw new FamilyExcepiton(FailCode.PARAMS_ERROR);
		}
		 FamilyMember  member = familyMemberService.findByUserId(uid);
	    //是否消息免打扰。0：否 1：是
		result.put("nocall", member.getNocall());
		//是否家族屏蔽消息 0：否 1：是
		result.put("shield", member.getShield());
		return result;
	}

   private boolean updateNocall(Family family, FamilyMember familyMember,String userNo,int nocall) throws ParseException, IOException, CFException {
	    FamilyMember memberParam=new FamilyMember();
	    memberParam.setId(familyMember.getId());
	    memberParam.setNocall(nocall);
		familyMemberService.update(memberParam);

    	wyService.muteTeam(family.getTid(), userNo, nocall);
		return true;
	}

	private List<Map<String, Object>> formatTopFamily(Long userId, List<Long> list) throws CFException {
		List<Map<String, Object>> result = null;
		if (list != null && !list.isEmpty()) {
			result = new ArrayList<>();
			Map<String, Object> map = null;
			for (Long familyId : list) {
				if (familyId == null) {
					continue;
				}

				map = new HashMap<>();
				Family family = this.findById(familyId);
				map.put("name", family.getName());
				map.put("icon", family.getFicon());
				map.put("id", family.getId());

				User user = userService.findById(family.getOwner_user_id());
				boolean isFansFamily = user.getSuper_id() != null && user.getSuper_id() == userId;
				map.put("isFansFamily", isFansFamily);
				result.add(map);
			}
		}

		return result;
	}

	@Override
	public Family findFamilyByUserId(Long userId)  {
		FamilyMember familyMember = familyMemberService.findByUserId(userId);
		log.debug("find family by user id ={}, member={}", userId, familyMember);
		if (familyMember == null) {
			return null;
		}
		Long family_id = familyMember.getFamily_id();
	    Family family = findById(family_id);
	    return family;
	}

	@Override
	public void refreshRank(String time) throws CFException {
		log.debug("更新家族排行=======>开始。time={}",time);
		List<Map<String,Object>> list = baseDao.findRankFamily(time);

		if(list!=null && !list.isEmpty()){
			for (Map<String, Object> map : list) {
				Long familyId = MapUtils.getLongValue(map, "id");
				int rownum = MapUtils.getIntValue(map, "rownum");
				Family family = this.findById(familyId);
				if (family == null) {
					log.error("更新家族排行=======》refreshRank is null。time={}",time);
					continue;
				}
				Family familyParam=new Family();
				familyParam.setId(family.getId());
				familyParam.setY_rank(rownum);
				this.update(familyParam);
			}
		}
		cacheService.delete(KEY_PREFIX.familyRank_.name());
		log.debug("更新家族排行=======>结束。time={}",time);
	}

	@Override
	public Family findById(Object fid) {
		
		return  baseDao.findById(fid);
		
	/* 	Family family = (Family)cacheService.get(CacheService.KEY_PREFIX.family_.name() + fid);
		log.debug("find family id ={}, family={}", fid, family);
	 	if (family == null) {
	 		family = baseDao.findById(fid);
	 		log.debug("findById family id ={}, family={}", fid, family!=null?family.getAnnouncement():"");
	 		if (family != null) {
	 			family.setVersion(System.currentTimeMillis());
	 			cacheService.set(CacheService.KEY_PREFIX.family_.name() + fid, family,300000);
			}
		}

		return family;*/
	}

	@Override
	public Family getByOwner(Long userId) throws CFException {
		return  baseDao.findByOwnerId(userId);
	}

	@Override
	public boolean addFamilyBylogin(Long userId,Long excludeFamilyId) throws CFException {
        User user = userService.findById(userId);
        if (user == null) {
            log.info("分配家族=====>user is null。userId={}", userId);
            return false;
        }

        if (user.getIs_admin() != null && user.getIs_admin() == 1) { //客服账号不用分配
            log.info("分配家族=====>客服账号不用分配 。isAdmin={}", user.getIs_admin());
            return true;
        }
        if(excludeFamilyId==null){
        	Long lastFamilyId=baseDao.findFamilyByLastDelete(userId);
			if (lastFamilyId != null) {
				excludeFamilyId = lastFamilyId;
			}
        	
        }

        //分配优先级--》 上级家族、随机分配家族、系统家族
        boolean result = addSuperFamilyBylogin(user, excludeFamilyId);
        if (!result) {
            result = addRandomFamilyBylogin(user, excludeFamilyId);
            if (!result) {
                result = addSystemFamilyBylogin(user, excludeFamilyId);
            }
        }

        log.info("分配家族 =======>,result={},excludeFamilyId={}", result, excludeFamilyId);
        return result;
    }

	/**
	 * 分配用户到系统家族
	 * @param user
	 * @param excludeFamilyId
	 * @return
	 * @throws CFException
	 * @throws IOException
	 * @throws ParseException
	 */
	private boolean addSystemFamilyBylogin(User user, Long excludeFamilyId) throws CFException {
		int memberCount = sysConfigService.getIntegerValue(SysConfigKeyEnum.system_family_max.toString(), FamilyConstance.FAMILY_CAPACITY);
		List<Family> list = baseDao.findSystemFamily(memberCount);
		if(list != null && !list.isEmpty()){
			for (Family family : list) {
				if(family.getId().equals(excludeFamilyId)){
					log.info("分配用户到系统家族======>排除指定家族,uid={}，excludeFamilyId={}", user.getId(),excludeFamilyId);
					continue;
				}

				boolean success = familyMemberService.addFamilyMember(family, user, true, false);
				if(success){
					log.info("分配用户到系统家族成功======>加入家族{} ,uid={},family_id={}", success, user.getId(),family.getId());
					return success;
				}
			}

		}
		log.info("分配用户到系统家族======>加入家族失败 ,uid={}", user.getId());
		return false;
	}

	/**
	 * 随机分配家族
	 *
	 * @param user
	 * @param excludeFamilyId
	 * @return
	 * @throws CFException
	 * @throws IOException
	 * @throws ParseException
	 */
	private boolean addRandomFamilyBylogin(User user, Long excludeFamilyId) throws CFException {
//		1.Select 家族表 Top 1 where家族人数<200 and 族长最后登陆时间<3天 order by 家族人数DESC
		long login_random_login_time = sysConfigService.getLongValue(SysConfigKeyEnum.login_random_login_time.toString(),
				FamilyConstance.LEADER_LOST_TIME_SPAN);
		Timestamp time = new Timestamp(System.currentTimeMillis() - login_random_login_time);
		int count = 200;
		Family family = null;
		do {
			Map<String, Object> param=new HashMap<String, Object>();
			param.put("memberCount", count);
			param.put("loginTime", time);
			param.put("excludeFamilyId", excludeFamilyId);
			family = baseDao.findRandomFamily(param);
			log.debug("addRandomFamilyBylogin=======> family uid={},count={}, loginTime={}, family={}",user.getId(), count, time, family);

			count += 100;
		} while (family == null && count <= 400);

		if(family != null){
			boolean result=familyMemberService.addFamilyMember(family, user, true, false);
			if(result){
				log.info("随机分配家族======>分配随机家族成员成功 ,uid={},familyId={}", user.getId(),family.getId());
			}
			return result;

		} else {
			log.info("随机分配家族=========>分配随机家族成员失败");
			return false;

		}
	}

	/**
	 * 分配用户到上级家族
	 *
	 * @param user
	 * @param excludeFamilyId
	 * @return
	 * @throws CFException
	 * @throws IOException
	 * @throws ParseException
	 */
	private boolean addSuperFamilyBylogin(User user, Long excludeFamilyId) throws CFException {
		Long super_id = user.getSuper_id();
		Long uid = user.getId();
		if (super_id == null) {
			log.info("分配用户到上级家族======>不存在上级。uid={},super_id={}",uid,super_id);
			return false;
		}

		Family superFamily = familyService.findFamilyByUserId(super_id);
		if(superFamily==null){
			log.info("分配用户到上级家族======>上级没有家族。uid={}",uid);
			return false;
		}
		if(excludeFamilyId!=null && excludeFamilyId.intValue() == superFamily.getId()){
			log.info("分配用户到上级家族======>排除指定家族。。uid={},excludeFamilyId={}",uid,excludeFamilyId);
			return false;
		}

		long loginSuperLoginTime = sysConfigService.getLongValue(SysConfigKeyEnum.login_super_login_time.toString(),
				FamilyConstance.LEADER_LOST_TIME_SPAN);
		User superfamilyOwner = userService.findById(superFamily.getOwner_user_id());
		if (superfamilyOwner.getActive_time() == null) {
			log.info("分配用户到上级家族======>上线三天未登录 。uid={},timt={}",uid, superfamilyOwner.getActive_time());
			return false;
		}

		long login_time = superfamilyOwner.getActive_time().getTime();
		boolean validLoginTime=  (System.currentTimeMillis() - login_time) < loginSuperLoginTime;
		if(validLoginTime){
			boolean suucess = familyMemberService.addFamilyMember(superFamily, user, true, false);
			log.info("分配用户到上级家族======>分配{}。uid={},validLoginTime={},", suucess, uid,validLoginTime);
			return suucess;

		} else {
			log.info("分配用户到上级家族======>分配失败。uid={},validLoginTime={},", uid,validLoginTime);
			return false;

		}
	}

	@Override
	public int announcement_read(Long uid,String tid) throws CFException {
		User user = userService.findById(uid);
		if (user == null) {
			throw new FamilyExcepiton(FailCode.USER_NOT_EXIST);
		}

		Family family = this.findFamilyByUserId(uid);
		FamilyValidator.validateFamilyTid(family, tid);

		FamilyMember familyMember = familyMemberService.findByUserId(uid);
		if (familyMember == null) {
			throw new FamilyExcepiton(FailCode.FAMILY_MEMBER_NOT_EXIST);
		}
		if(familyMember.getAnnouncement_read()==null || familyMember.getAnnouncement_read()==0){

			FamilyMember memberParam=new FamilyMember();
			memberParam.setId(familyMember.getId());
			memberParam.setAnnouncement_read(1);

			familyMemberService.update(memberParam);
		}

		Map<String, Object> param=new HashMap<String, Object>();
		param.put("announcement_read", 1);
		param.put("family_id", familyMember.getFamily_id());
		return familyMemberService.searchCount(param);
	}

	@Override
	public List<User> getCanDeleteMember(Long uid,
			String keyword, Integer p,String tid) throws CFException {
		Family family = this.findFamilyByUserId(uid);
		FamilyValidator.validateFamilyTid(family, tid);

		Long familyId = family.getId();
		long kick_login_time = sysConfigService.getLongValue(SysConfigKeyEnum.kick_login_time.toString(),FamilyConstance.LEADER_LOST_TIME_SPAN);
		long lt_login_time=System.currentTimeMillis()-kick_login_time;

		Map<String, Object> param=new HashMap<String, Object>();
		param.put("family_id", familyId);
		param.put("owner_user_id", family.getOwner_user_id());
		param.put("kick_login_time", new Timestamp(lt_login_time));
		param.put("keyword", keyword);
		param.put("column_sort", "u.login_time");
		param.put("column_order", "DESC");
		Page page = p != null ? new Page(p) : null;
		return baseDao.findCanDeleteMember(param, page);

	}

	@Override
	public Map<String, Object> getFamilyNotice(Long uid,String tid) throws CFException, ParseException, java.text.ParseException {
		Map<String, Object> result = new HashMap<>();

		User user = userService.findById(uid);
		if (user == null) {
			throw new CFException(FailCode.USER_NOT_EXIST);
		}
		Family family=null;
		FamilyMember familyMember = familyMemberService.findByUserId(uid);
		if (familyMember == null) {
			result.put("tid", "");
		}else{
			family= this.findById(familyMember.getFamily_id());
			if(family==null){
				result.put("tid", "");
			}else{
				if(tid!=null && !"".equals(tid)){
					if(!tid.equals(family.getTid())){
						result.put("tid", family.getTid());
					}
				}
			}
			
		}
		
		if(result.get("tid")!=null){
			result.put("leave_notice", false);
			result.put("packet_notice", false);
			result.put("memberCount", 0);//当前成员数
			result.put("name", "");//当前成员数
			result.put("shield", 0);
			return result;
		}
		

		boolean leave_notice=getLeaveNotice(user,family,familyMember);
		boolean packet_notice=getPacketNotice(user, familyMember);
		result.put("leave_notice", leave_notice);
		result.put("packet_notice", packet_notice);
		result.put("memberCount", familyMemberService.searchCountByFamilyId(familyMember.getFamily_id()));//当前成员数
		result.put("name", family.getName());//当前成员数
		//是否家族屏蔽消息 0：否 1：是
		result.put("shield", familyMember.getShield());
		result.put("tid", family.getTid());
		return result;
	}

	private boolean getLeaveNotice(User user,Family family, FamilyMember familyMember) throws CFException,
			java.text.ParseException {
		Long uid=user.getId();
		Long owner_user_id = family.getOwner_user_id();
		if(uid==owner_user_id.longValue()){
			return false;
		}else{
			Timestamp leave_notice = familyMember.getLeave_notice();
			User ower = userService.findById(owner_user_id);
			if (ower == null) {
				throw new CFException(FailCode.USER_NOT_EXIST);
			}
			long leave_login_time = sysConfigService.getLongValue(SysConfigKeyEnum.leave_login_time.toString(),FamilyConstance.LEADER_LOST_TIME_SPAN);
			boolean allow_leave=ower.getActive_time()!=null && System.currentTimeMillis() - ower.getActive_time().getTime() < leave_login_time;
			if(allow_leave){//族长三天内登陆过，不显示通知
				return false;
			}else{
				if(leave_notice!=null && daysBetween(new Date(leave_notice.getTime()),new Date(System.currentTimeMillis()))==0){
					return false;
				}
				return true;

			}
		}
	}

	private boolean getPacketNotice(User user, FamilyMember familyMember)
			throws java.text.ParseException {
		Timestamp packet_notice = familyMember.getPacket_notice();
		Date tdate = new Date(System.currentTimeMillis());
		if(packet_notice!=null && daysBetween(new Date(packet_notice.getTime()), tdate) == 0){ //今日已经忽略
			return false;
		}

		return !userDayIncomeService.isDayUserShared(user.getId(), CkUtil.getNowDayStr());
	}

	@Override
	public boolean ignoreNotice(Long uid,int type,String tid) throws CFException {
		FamilyMember familyMember = familyMemberService.findByUserId(uid);
		if(familyMember==null){
			throw new CFException(FailCode.FAMILY_MEMBER_NOT_EXIST);
		}
		Family family = this.findById(familyMember.getFamily_id());
		FamilyValidator.validateFamilyTid(family, tid);

		FamilyMember memberParam=new FamilyMember();
		memberParam.setId(familyMember.getId());
		if(type==1){
			memberParam.setLeave_notice(new Timestamp(System.currentTimeMillis()));
		}else if(type==2){
			memberParam.setPacket_notice(new Timestamp(System.currentTimeMillis()));
		}else {
			throw new CFException(FailCode.PARAMS_ERROR);
		}
		familyMemberService.update(memberParam);
		return true;
	}

	@Override
	public void initRank() {
		List<Long> topFamily = baseDao.getFamilyByRank(10);
		if(topFamily==null || topFamily.isEmpty()){
			Map<String, Object> param=new HashMap<String, Object>();
			param.put("type", 2);
			List<Map<String, Object>> search = baseDao.search(param);
			if(search!=null && !search.isEmpty()){
				int num=0;
				for (Map<String, Object> map : search) {
					Long id=MapUtils.getLong(map, "id");
					Family update=new Family();
					update.setId(id);
					update.setY_rank(++num);
					this.update(update);
				}
			}
			
		}
	}
	
	@Override
	public List<Long> getAllFamilyId() {
		return baseDao.getAllFamilyId();
	}
}